/**
 * BulkSMSKannelSbb
 * 
 * The SBB receives HTTP requests from predecessor that are destined for submission to Kannel GSM Gateway
 */
package org.convergence.services.slee.bulksms.kannel;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.slee.*;
import javax.slee.facilities.Tracer;

import org.mobicents.slee.SbbContextExt;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;

import net.java.client.slee.resource.http.HttpClientActivity;
import net.java.client.slee.resource.http.HttpClientActivityContextInterfaceFactory;
import net.java.client.slee.resource.http.HttpClientResourceAdaptorSbbInterface;
import net.java.client.slee.resource.http.event.ResponseEvent;
import net.java.slee.resource.http.events.HttpServletRequestEvent;

public abstract class BulkSMSKannelSbb implements Sbb {
	
	private Tracer tracer;
	private String strTo;
	private String strText;
	
	private String strServerAddress;
	private String strServerPort;
	private String strServerPath;
	private String strKannelUsername;
	private String strKannelPassword;
	
	private HttpClientActivityContextInterfaceFactory httpClientAci;
	private HttpClientResourceAdaptorSbbInterface raSbbInterface;
	
	public void onServiceStartedEvent(javax.slee.serviceactivity.ServiceStartedEvent event, KannelSbbActivityContextInterface aci) {
		tracer.info("Bulk SMS Kannel Service Started");
	}
	
	/*
	 * OnGet: process the GET operation from an external system
	 * 		: method compiles the URL properly for submission to Kannel
	 * in:
	 * 		HttpServletRequestEvent: the http type event from the RA
	 * 		ActivityContextInterface: the activity context associated with the event
	 */
	public void onGet(HttpServletRequestEvent event, KannelSbbActivityContextInterface aci) {
		tracer.info("Received GET operation");
		
		if(aci.getProcessedByPredecessor()) {
			tracer.info("Processed by Predecessor");
			
			strTo = aci.getToInKannel();
			strText = aci.getTextInKannel();
			
			String url = "http://"+strServerAddress+":"+strServerPort+"/"+strServerPath+"?username="+strKannelUsername+
			"&password="+strKannelPassword+"&to="+strTo+"&text="+strText;
			
			tracer.info(url);
			
			HttpGet httpGet = new HttpGet(url);
		
			try{
				HttpClientActivity clientActivity = raSbbInterface
	            .createHttpClientActivity(true, null);
				
				ActivityContextInterface clientAci = httpClientAci
	            .getActivityContextInterface(clientActivity);
				
				clientAci.attach(sbbContext.getSbbLocalObject());
				
				clientActivity.execute(httpGet, null);
	
			}
			catch (Throwable e){
				tracer.severe("Error while creating HTTPClientActivity");
				e.printStackTrace();
			} 
			finally{
				/* set set by attribute and detach from activity context */
				aci.setProcessedByMe(true);
				SbbLocalObject sbbLocalObject = sbbContext.getSbbLocalObject();
		        aci.detach(sbbLocalObject);
			}
		}
		else {
			tracer.info("Not processed by Predecessor");
			/* set set by attribute and detach from activity context */
			aci.setProcessedByMe(false);
			SbbLocalObject sbbLocalObject = sbbContext.getSbbLocalObject();
	        aci.detach(sbbLocalObject);
		}
	}
	
	/*
	 * onResponseEvent:		invoked when the response is received back from Kannel regarding the status of the previous request
	 * 
	 * 	in:
	 * 		event - the Response Event object from Kannel
	 * 		aci - the Kannel custom activity context associated with the event
	 */
	public void onResponseEvent(ResponseEvent event, KannelSbbActivityContextInterface aci){
		HttpResponse response = event.getHttpResponse();
        tracer.info("********** onResponseEvent **************");
        tracer.info("URI = " + event.getRequestApplicationData());
        tracer.info("Status Code = " + response.getStatusLine().getStatusCode());
        try {
                tracer.info("Response Body = "
                                + EntityUtils.toString(response.getEntity()));
        } catch (Exception e) {
                tracer.severe("Failed reading response body", e);
        }
        tracer.info("*****************************************");
	}

	/*
	 * (non-Javadoc)
	 * @see javax.slee.Sbb#setSbbContext(javax.slee.SbbContext)
	 * Beginning of the life cycle of the SBB - the SBB grabs information configured in the <entry> params in the sbb-jax.xml file for
	 * 											communicating with Kannel and also instantiates HTTP client facilities for the HTTP GET and response
	 * 		in:
	 * 			SbbContext - object passed to the Sbb from the SLEE
	 */
	public void setSbbContext(SbbContext context) { 
		this.sbbContext = (SbbContextExt) context; 
		tracer = sbbContext.getTracer(getClass().getSimpleName()); 
		
		try {
            Context myEnv = (Context) new InitialContext().lookup("java:comp/env");
			this.strServerAddress = (String) myEnv.lookup("serverAddress");
			this.strServerPort = (String) myEnv.lookup("serverPort");
			this.strServerPath = (String) myEnv.lookup("serverPath");
			this.strKannelUsername = (String) myEnv.lookup("serverUsername");
			this.strKannelPassword = (String) myEnv.lookup("serverPassword");
            httpClientAci = (HttpClientActivityContextInterfaceFactory) myEnv.lookup("slee/resources/http-client/acifactory");
            raSbbInterface = (HttpClientResourceAdaptorSbbInterface) myEnv.lookup("slee/resources/http-client/sbbinterface");
		} catch (NamingException ne) {
            tracer.severe("Could not set SBB context:", ne);
		}
	}
	public void unsetSbbContext() { this.sbbContext = null; }

	// TODO: Implement the lifecycle methods if required
	public void sbbCreate() throws javax.slee.CreateException {}
	public void sbbPostCreate() throws javax.slee.CreateException {}
	public void sbbActivate() {}
	public void sbbPassivate() {}
	public void sbbRemove() {}
	public void sbbLoad() {}
	public void sbbStore() {}
	public void sbbExceptionThrown(Exception exception, Object event, ActivityContextInterface activity) {}
	public void sbbRolledBack(RolledBackContext context) {}
	
	public abstract org.convergence.services.slee.bulksms.kannel.KannelSbbActivityContextInterface asSbbActivityContextInterface(ActivityContextInterface aci);

	/**
	 * Convenience method to retrieve the SbbContext object stored in setSbbContext.
	 * 
	 * TODO: If your SBB doesn't require the SbbContext object you may remove this 
	 * method, the sbbContext variable and the variable assignment in setSbbContext().
	 *
	 * @return this SBB's SbbContext object
	 */
	
	protected SbbContextExt getSbbContext() {
		return sbbContext;
	}

	private SbbContextExt sbbContext; // This SBB's SbbContext
}
